<template>
  <div class="home">
    <div class="mt-20 ml-10 ">
      <p>选择 Swagger Api</p>
      <el-select v-model="activeKey" @change="getOncePath()" clearable placeholder="请选择 Sawagger Api"
        style="width: 800px">
        <el-option v-for="item in pathsKeys" :key="item" :label="item" :value="item" />
      </el-select>
      <p>Api 内容</p>
      <div style="margin-top: 20px;">
        <codemirror v-model="code" placeholder="Code goes here..." :style="{ height: '600px' }" :autofocus="true"
          :indent-with-tab="true" :tab-size="2" :extensions="extensions" />
      </div>
      <!-- :extensions="extensions" @ready="handleReady"
        @change="log('change', $event)" @focus="log('focus', $event)" @blur="log('blur', $event)" -->
      <p style="margin-top: 20px;">
        <el-button type="default" @click="download()">下载</el-button>
        <el-button type="default" @click="countRow()">统计总代码行数</el-button>
      </p>
      <p style="color: red;">代码总行数： {{ sumCount }}</p>
    </div>


  </div>
</template>

<script lang="ts">
import { Options, Vue } from "vue-class-component";
import receptionSwaggerJson from '@/assets/json/reception';
import _, { create } from "lodash";
import { PathsItemType, PathsType } from "@/assets/json/Paths.type";
import { RequestBodyItemTemplate, RequestBodyFrameTemplate, ParametersItemTemplate, ParametersFrameTemplate } from "@/assets/template/request/RequestTemplate";
import { Codemirror } from 'vue-codemirror'
import { javascript } from '@codemirror/lang-javascript'
import { oneDark } from '@codemirror/theme-one-dark'
import { createFile } from '../common/http.api'
import { CreateFileInputDto } from "@/models/apis/file";
import { ElMessage } from "element-plus";

@Options({
  components: {
    Codemirror
  },
})
export default class HomeView extends Vue {
  private pathsKeys: Array<string> = [];
  private paths: PathsType = {};
  private activeKey: string = "";
  private avtivePath: PathsItemType = {};
  private parametersModelStr: String = "";
  private requestBodyModelStr: String = "";
  private code: string = "";
  private countCode: string = "";
  private sumCount: number = 0;

  private createFileInputDto?: CreateFileInputDto = undefined;

  private getOncePath(isCountRowFlag: boolean = false) {
    console.log(this.activeKey);
    if (Object.prototype.hasOwnProperty.call(this.paths, this.activeKey)) {
      // 匹配一个模型数据
      this.avtivePath = this.paths[this.activeKey];
      // 生成 Parameters 模型
      this.generateParametersModel();
      // 生成 RequestBody 模型
      this.generaterequestBodyModel();

      // 不是统计代码才给 code 赋值
      if (!isCountRowFlag) {
        // 获取 code
        this.code = this.parametersModelStr.toString() + this.requestBodyModelStr;
      } else {
        this.countCode = this.parametersModelStr.toString() + this.requestBodyModelStr;
      }
    }
  }

  private countRow() {
    this.sumCount = 0;

    this.pathsKeys.forEach((key, i) => {
      this.activeKey = key;
      this.getOncePath(true);
      this.sumCount += this.countCode.split('\n').length;
    });

  }

  private extensions = [javascript(), oneDark];

  private generateParametersModel() {
    var obj = this.avtivePath.get ? this.avtivePath.get : this.avtivePath.post;
    var parameters = obj?.parameters;

    // parameters 为空, 直接返回
    if (!parameters)
      return;

    var parametersStr = "";
    for (let i = 0; i < parameters.length; i++) {
      var item = parameters[i];

      // 实例化 item 对象
      var itemInfo = {
        description: item.description,
        explode: item.explode,
        _in: item.in,
        required: item.required,
        name: item.name,
        type: item.schema.type
      };

      // 使用 format 进行模板转换
      var itemStr = ParametersItemTemplate.format(itemInfo);
      parametersStr += itemStr;
    }

    // 生成模型对应的对象
    var modelName = this.getModelName("ParametersModel");
    this.parametersModelStr = ParametersFrameTemplate.format(modelName, parametersStr);
  }

  /**
   * 生成请求 RequestBody 的模型
   */
  private generaterequestBodyModel() {
    // get 类型请求不含 requestBody ，直接返回
    if (this.avtivePath.get)
      return;

    // requestBody 为空 ，直接返回
    var requestBody = this.avtivePath.post?.requestBody;
    if (!requestBody)
      return;

    // properties 为空 ，直接返回
    var properties = requestBody?.content["application/json"]?.schema?.properties;
    if (!properties)
      return;

    var requetBodyStr = "";
    for (const key in properties) {

      // 实例化 item 对象
      var itemInfo = {
        name: key,
        comment: properties[key]?.comment ?? '',
        text: properties[key]?.text ?? '',
        example: properties[key]?.example ?? '',
        format: properties[key]?.format ?? '',
        type: properties[key]?.type ?? '',
      };

      // 使用 format 进行模板转换
      var itemStr = RequestBodyItemTemplate.format(itemInfo);
      requetBodyStr += itemStr;
    }

    // 生成模型对应的对象
    var modelName = this.getModelName("RequestBodyModel");
    this.requestBodyModelStr = RequestBodyFrameTemplate.format(modelName, requetBodyStr);
  }


  /**
   * 获取模型或者文件名称
   * @param suffix 后缀
   */
  private getModelName(suffix: string) {
    var modelName = this.activeKey.split('/').reverse()[0];
    modelName = modelName.replaceAll("-", "_");
    modelName = this.toHump(modelName);

    modelName = modelName + suffix
    return modelName;
  }

  /**
   * 带下划线的字符串转小驼峰
   * @param lineStr 带下划线的字符串
   */
  private toHump(lineStr: string) {
    return lineStr.replace(/\_(\w)/g, function (all, letter) {
      return letter.toUpperCase();
    });
  }


  private getPath() {
    let lastIndex = this.activeKey.lastIndexOf('/');
    let path = this.activeKey.substring(0, lastIndex);
    return path;
  }


  /**
* 创建一个 formdata 数据，用于文件类型 post 请求提交
* @param {*} objData 对象类型数据
* @returns 
*/
  private createFormData(objData: any) {
    var formdata = new FormData();
    for (const key in objData) {
      formdata.append(key, objData[key]);
    }
    return formdata;
  }


  /**
   * 下载文件
   */
  private async download() {
    var fileName = this.getModelName("Model") + ".ts";
    var path = this.getPath();
   
    const stringData = this.parametersModelStr.toString() + this.requestBodyModelStr;
    // dada 表示要转换的字符串数据，type 表示要转换的数据格式
    const blob = new Blob([stringData], {
      type: "text/plain;charset=utf-8"
    })
    // 获取 File 类型文件
    const file = new  File([blob], fileName, {type: "text/plain;charset=utf-8", lastModified: Date.now()});

    this.createFileInputDto = {
      FileName: fileName,
      Path: path,
      File:file
    }

    var from  = this.createFormData(this.createFileInputDto);
    console.log("from.FileName",from.getAll('FileName'));
    console.log("from.Path",from.getAll('Path'));
    console.log("from.File",from.getAll('File'));
 
    var res = await createFile(from);
    console.log(res);
    ElMessage.success(res) 
  }

  beforeCreate() {
    // 深拷贝数据
    var paths = _.cloneDeep(receptionSwaggerJson.paths);

    // 初始化 api 下拉列表数组
    this.paths = paths;
    for (const key in paths) {
      this.pathsKeys.push(key);
    }
  }

}
</script>